package onion;

import java.io.*;
import java.util.*;
import java.net.*;
import onion.NodeAddress;
/**
 * 
 * @author xDEMONx
 * Сервер каталогов
 */
public class OnionDB {
    //Порт сервера каталога
    static int DB_port = 1315;    
    //Конфигурационный файл с указанием порта   
    static String ConfFile = "DB.conf";
    //Список узлов
    Vector<NodeAddress> listNodes;        
    //Поток для выдачи списка
    class Worker extends Thread{        
        Socket s;       
        int listSize;
        public Worker(Socket s, int listSize){
            this.s = s;
            this.listSize = listSize;
        }
        public void run(){
            try{                                      
                ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
                out.writeInt(listSize);                               
                for(int i = 0; i < listSize; i++){
                    out.writeObject(listNodes.get(i));
                }
                out.close();                
                s.close();
            }
            catch(Exception e){}
        }        
    }                
    //Добавление в список нового узла
    void addNode(ObjectInputStream in, String HostAddress){        
        try{
            NodeAddress na = (NodeAddress)in.readObject();
            if(!na.IP.equals(HostAddress)){
                System.out.printf("Different address. I get \"%s\", "
                        + "but I see \"%s\"\n",na.IP,HostAddress);
                na.IP = HostAddress;
            }            
            listNodes.add(na);
            System.out.println("Added node ("+na.IP+":"+na.port+")");
        }catch(Exception e){}
    }    
    //Выдача списка узлов
    void giveList(Socket s){
        Worker w = new Worker(s,listNodes.size());
        w.setDaemon(true);
        w.start();
    }    
    public static void main(String[] args) throws IOException {
       new OnionDB().run();
    }
    void run() throws IOException{
        listNodes = new Vector<>();
        try{
            //Попытка считать порт из файла
            Scanner fileIn = new Scanner(new FileReader(ConfFile));
            DB_port = fileIn.nextInt();
            fileIn.close();
        }
        catch(FileNotFoundException e){    
            //Файла не нашлось, пишем сами
            PrintWriter fileOut = new PrintWriter(new FileWriter(ConfFile));
            fileOut.print(DB_port);            
            fileOut.close();
        }
        try{            
            ServerSocket server = new ServerSocket(DB_port);
            System.out.println("OnionDB is started on port "+DB_port);                        
            //Рабочий цикл программы
            while(true){
                Socket s = server.accept();            
                ObjectInputStream in = new ObjectInputStream(s.getInputStream());                
                //Считываем команду (либо добавление узла, либо получение списка)
                String command = in.readUTF();                                
                switch(command){
                    case "add":
                        addNode(in, s.getInetAddress().getHostAddress());                        
                        s.close();
                        break;
                    case "list":                                                
                        giveList(s);                        
                        break;
                    default:
                        System.out.println("Unknown command");                        
                }                              
            }
        }
        catch(Exception e){
            System.out.println("Error: "+e);
        }
    }
}
